#ifndef RECURSODEALMACENAMIENTO_H_
#define RECURSODEALMACENAMIENTO_H_

#include <string>

#include "Indice.h"
#include "Buffer.h"
#include "Almacenamiento.h"
#include <list>
#include <string>

enum enumAlmacenamiento { TEXTO, REGISTROS, BLOQUES };
enum enumRecurso { UN_ALMACENAMIENTO, ESCRITURA_DIRECTA, ESCRITURA_DIFERIDA };
enum enumIndice { HASH_EXTENSIBLE, BSHARP, NO_INDEXADO };

class RecursoDeAlmacenamiento;

class EstrategiaRecurso{
	public:
		virtual void crear(RecursoDeAlmacenamiento* recurso, enumAlmacenamiento estAlmacenamiento, enumIndice estIndice, int longitudBuffer, int longitudBloqueIndice, int longitudBloque) = 0;
		virtual void almacenar(RecursoDeAlmacenamiento* recurso, Registro registro) = 0;
		virtual void modificar(RecursoDeAlmacenamiento* recurso, Registro registro, int offset) = 0;
		virtual void borrar(RecursoDeAlmacenamiento* recurso, int offset, list<string> claves) = 0;
		virtual Registro buscar(RecursoDeAlmacenamiento* recurso, int offset, list<string> claves) = 0;
		virtual void cerrar(RecursoDeAlmacenamiento* recurso) = 0;
};

//Clase que define una interfaz para el trabajo con un recurso de Almacenamiento.
class RecursoDeAlmacenamiento{
	public:

		RecursoDeAlmacenamiento();
		RecursoDeAlmacenamiento(enumIndice estIndice, enumAlmacenamiento estAlmacenamiento, enumRecurso estRecurso, std::string& nombreArchivo, int longitudBuffer, int longitudBloqueIndice, int longitudBloque);
		//interfaz para el cliente
		void almacenar(Registro& registro);
		void borrar(list<string> claves) throw (int);
		void modificar(Registro& registro);
		void cerrar();
		Registro buscar(list<string> claves);
		
		//impresion
		void imprimirBuffer();
		void imprimirIndice();
		void imprimirArchivo();

		//getters y setters
		Archivo* getArchivo();
		Indice* getIndice();
		Buffer* getBuffer();
		string& getNombreArchivo();
		void setArchivo(Archivo*);
		void setIndice(Indice*);
		void setBuffer(Buffer*);
		void setNombreArchivo(string nombre);
	private:
		Archivo* archivo;
		Indice* indice;
		Buffer* buffer;
		string nombreArchivo;
		EstrategiaRecurso* estrategiaRec;
};

//Estrategia de almacenamiento con un solo recurso.
class EstrategiaRecursoUnAlmacenamiento: public EstrategiaRecurso{
	public:
		void crear(RecursoDeAlmacenamiento* recurso, enumAlmacenamiento estAlmacenamiento, enumIndice estIndice, int longitudBuffer, int longitudBloqueIndice, int longitudBloque);
		void almacenar(RecursoDeAlmacenamiento* recurso, Registro registro);
		void modificar(RecursoDeAlmacenamiento* recurso, Registro registro, int offset);
		void borrar(RecursoDeAlmacenamiento* recurso, int offset, list<string> claves);
		Registro buscar(RecursoDeAlmacenamiento* recurso, int offset, list<string> claves);
		void cerrar(RecursoDeAlmacenamiento* recurso);
	private:
		void crearIndice(RecursoDeAlmacenamiento* recurso, EstrategiaAlmacenamiento* eAlmacenamiento, enumIndice estIndice, int longitudBloqueIndice, int longitudBloque);
};

//Estrategia de almacenamiento con un Buffer y un Archivo, donde se aplica el algoritmo de Escritura Directa.
class EstrategiaRecursoEscrituraDirecta: public EstrategiaRecurso{
	public:
		void crear(RecursoDeAlmacenamiento* recurso, enumAlmacenamiento estAlmacenamiento, enumIndice estIndice, int longitudBuffer, int longitudBloqueIndice, int longitudBloque);
		void almacenar(RecursoDeAlmacenamiento* recurso, Registro registro);
		void modificar(RecursoDeAlmacenamiento* recurso, Registro registro, int offset);
		void borrar(RecursoDeAlmacenamiento* recurso, int offset, list<string> claves);
		Registro buscar(RecursoDeAlmacenamiento* recurso, int offset, list<string> claves);
		void cerrar(RecursoDeAlmacenamiento* recurso);
	private:
		void crearIndice(RecursoDeAlmacenamiento* recurso, EstrategiaAlmacenamiento* eAlmacenamiento, enumIndice estIndice, int longitudBloqueIndice, int longitudBloque);
};

//Estrategia de almacenamiento con un buffer y un Archivo, donde se aplica el algoritmo de Escritura Diferida.
/*class EstrategiaRecursoEscrituraDiferida: public EstrategiaRecurso{
	public:
		void crear(RecursoDeAlmacenamiento* recurso, enumAlmacenamiento estAlmacenamiento, enumIndice estIndice, int longitudBuffer, int longitudBloqueIndice, int longitudBloque);
		void almacenar(RecursoDeAlmacenamiento* recurso, Registro registro);
		void modificar(RecursoDeAlmacenamiento* recurso, Registro registro, int offset);
		void borrar(RecursoDeAlmacenamiento* recurso, int offset, list<string> claves);
		Registro buscar(RecursoDeAlmacenamiento* recurso, int offset, list<string> claves);
		void cerrar(RecursoDeAlmacenamiento* recurso);
	private:
		void crearIndice(RecursoDeAlmacenamiento* recurso, EstrategiaAlmacenamiento* eAlmacenamiento, enumIndice estIndice, int longitudBloqueIndice, int longitudBloque);
};*/

#endif /*RECURSODEALMACENAMIENTO_H_*/
